package com.bsoft.gol.hcs.specialist.dao;

import ctd.controller.exception.ControllerException;
import ctd.persistence.DAOFactory;
import ctd.persistence.annotation.DAOMethod;
import ctd.persistence.annotation.DAOParam;
import ctd.persistence.support.hibernate.HibernateSupportDelegateDAO;
import ctd.persistence.support.hibernate.template.AbstractHibernateStatelessResultAction;
import ctd.persistence.support.hibernate.template.HibernateSessionTemplate;
import ctd.persistence.support.hibernate.template.HibernateStatelessResultAction;
import ctd.util.converter.ConversionUtils;
import com.bsoft.gol.hcs.enumcase.ConditionFilterMethodEnum;
import com.bsoft.gol.hcs.enumcase.FollowTypeEnum;
import com.bsoft.gol.hcs.enumcase.InspectIndexEnum;
import org.hibernate.Query;
import org.hibernate.StatelessSession;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.transform.Transformers;
import com.bsoft.gol.hcs.specialist.bean.request.GroupChronicRecordQo;
import com.bsoft.gol.hcs.specialist.bean.response.CrucialRecordResponse;
import com.bsoft.gol.hcs.specialist.bean.response.CrucialTimeRecordList;
import com.bsoft.gol.hcs.specialist.bean.response.FactorData;
import com.bsoft.gol.hcs.specialist.bean.response.PatientSearchProcess;
import com.bsoft.gol.hcs.specialist.entity.ExamReportEntity;
import com.bsoft.gol.hcs.specialist.entity.FollowUpRouteDetailFactorRelation;
import com.bsoft.gol.hcs.specialist.entity.FusCrucialIndexRecord;
import com.bsoft.gol.hcs.specialist.entity.PatientSearchRuleDetail;
import com.bsoft.gol.hcs.utils.CommonUtils;
import com.bsoft.gol.hcs.utils.DateUtil;

import java.util.*;

import static com.bsoft.gol.hcs.enumcase.ConditionFilterMethodEnum.getEnumByKey;
import static com.bsoft.gol.hcs.enumcase.InspectIndexEnum.*;


/**
 * 检查报告dao
 *
 * @author lanyu
 * @date 2021年10月14日 11:06
 */
public abstract class ExamReportDAO extends HibernateSupportDelegateDAO<ExamReportEntity> {

    public ExamReportDAO() {
        this.setKeyField("examReportId");
    }

    @DAOMethod(sql = " from ExamReportEntity where reportId =:reportId and reportOrganization =:reportOrganization ")
    public abstract ExamReportEntity getExamReportByReportId(@DAOParam("reportId") String reportId, @DAOParam("reportOrganization") String reportOrganization);

    @DAOMethod(sql = "from ExamReportEntity where businessType=:businessType and visitId=:visitId")
    public abstract List<ExamReportEntity> queryExamReportEntityList(@DAOParam("businessType") String businessType, @DAOParam("visitId") String visitId);

    /**
     * 根据日期删除检验报告
     *
     * @param resultDate
     */
    @DAOMethod(sql = "delete from ExamReportEntity where execute_datetime <:resultDate and delete_flag !='1' ")
    public abstract void deleteInspectReportOverdueData(@DAOParam("resultDate") Date resultDate);

    /**
     * 查询同步数量
     *
     * @param startTime
     * @param endTime
     * @return
     */
    @DAOMethod(sql = "select count(1) from ExamReportEntity  where  executeDatetime>=:startTime and executeDatetime<=:endTime")
    public abstract Long getExamRecordByToday(@DAOParam("startTime") Date startTime, @DAOParam("endTime") Date endTime);

    /**
     * 更新删除标识
     */
    @DAOMethod(sql = "update ExamReportEntity set deleteFlag='1' where  businessId in(:businessIdList) ")
    public abstract void updateDeleteFlag(@DAOParam("businessIdList") List<String> businessIdList);

    /**
     * 根据检查报告查询患者信息
     *
     * @param patientSearchRuleDetail
     * @param recordStartTime
     * @param recordEndTime
     * @return
     */
    public List<PatientSearchProcess> queryPatientByExamReport(final PatientSearchRuleDetail patientSearchRuleDetail, final Date recordStartTime,
                                                               final Date recordEndTime) {
        HibernateStatelessResultAction<List<PatientSearchProcess>> action =
                new AbstractHibernateStatelessResultAction<List<PatientSearchProcess>>() {
                    @Override
                    public void execute(StatelessSession ss) throws Exception {
                        StringBuilder sqlBuilder = new StringBuilder();
                        sqlBuilder.append("SELECT " +
                                "e.source_patient_id as patientId, " +
                                "e.report_organization as organizationId, " +
                                "e.report_organization_name as organizationName, " +
                                "e.NAME AS patientName, " +
                                "e.sex AS patientSex, " +
                                "SUBSTRING_INDEX(e.age,'岁',1) AS patientAge, " +
                                "e.business_type AS source, " +
                                "e.id_card AS cardNumber, " +
                                "CASE " +
                                "WHEN e.business_type = 1 THEN " +
                                "e.clinic_id ELSE e.hospization_id " +
                                "END AS patientNumber, " +
//                                "( SELECT ft.telephone FROM fus_team_chronic_group_record ft WHERE e.id_card = ft
//                                .card_number ) as telephone, " +
                                "( SELECT GROUP_CONCAT( distinct f.chronic_disease_id ) FROM " +
                                "fus_team_chronic_group_record f WHERE e.id_card = f.card_number and f.apply_status =" +
                                " '1') AS chronicDiseaseIds," +
                                "( SELECT GROUP_CONCAT( distinct f.chronic_disease_name ) FROM " +
                                "fus_team_chronic_group_record f WHERE e.id_card = f.card_number and f.apply_status =" +
                                " '1') AS chronicDiseaseName  " +
                                "FROM " +
                                "exam_report e ");
                        sqlBuilder.append("where e.exam_item_code =:secondConditionCode ");
                        if (CommonUtils.isNotEmpty(recordStartTime) && CommonUtils.isNotEmpty(recordEndTime)) {
                            sqlBuilder.append(" and e.execute_datetime>=:recordStartTime and e.execute_datetime<=:recordEndTime ");
                        }
                        String secondConditionCode = patientSearchRuleDetail.getSecondConditionCode();
                        //条件筛选方法：1 范围(包含边界) 2 等于 3 大于 4 小于 5 大于等于 6 小于等于，7包含，8不包含 9 Between
                        Byte conditionFilterMethod = patientSearchRuleDetail.getConditionFilterMethod();
                        //检查的，要查询指标编码
                        FusCrucialIndexRecordDAO crucialIndexRecordDAO =
                                DAOFactory.getDAO(FusCrucialIndexRecordDAO.class);
                        FusCrucialIndexRecord fusCrucialIndexRecord =
                                crucialIndexRecordDAO.get(secondConditionCode);
                        if (fusCrucialIndexRecord == null) {
                            throw new ControllerException("不存在的关联指标，无法完成检索");
                        }
                        InspectIndexEnum indexEnum =
                                InspectIndexEnum.getEnumByKey(fusCrucialIndexRecord.getIndexCode());
                        if (indexEnum == null) {
                            setResult(Collections.emptyList());
                            return;
//                            throw new ControllerException("未实现的关联指标，无法完成检索");
                        }
                        ConditionFilterMethodEnum methodEnum = getEnumByKey(conditionFilterMethod);
                        //检查只有文本和定性(阴阳性)
                        if (IMAGE_DIAGNOSIS.equals(indexEnum)) {
                            switch (methodEnum) {
                                case CONTAIN:
                                    sqlBuilder.append(" and e.exam_diagnosis like :factorResultOne");
                                    break;
                                case NOT_INCLUDED:
                                    sqlBuilder.append(" and e.exam_diagnosis not like :factorResultOne");
                                    break;
                                default:
                                    throw new ControllerException("不合法的运算符");
                            }
                        }
                        if (EXAM_FINDING.equals(indexEnum)) {
                            switch (methodEnum) {
                                case CONTAIN:
                                    sqlBuilder.append(" and e.exam_descript like :factorResultOne");
                                    break;
                                case NOT_INCLUDED:
                                    sqlBuilder.append(" and e.exam_descript not like :factorResultOne");
                                    break;
                                default:
                                    throw new ControllerException("不合法的运算符");
                            }
                        }
                        if (YIN_YANG.equals(indexEnum)) {
                            switch (methodEnum) {
                                case CONTAIN:
                                    sqlBuilder.append(" and e.malignant in (:factorResultList) ");
                                    break;
                                case NOT_INCLUDED:
                                    sqlBuilder.append(" and e.malignant not in (:factorResultList) ");
                                    break;
                                default:
                                    throw new ControllerException("不合法的运算符");
                            }
                        }
                        Query query = ss.createSQLQuery(sqlBuilder.toString());
//                        query.setParameter("firstConditionCode", patientSearchRuleDetail.getFirstConditionCode());
                        query.setParameter("secondConditionCode", secondConditionCode);
                        //检查只有文本和定性(阴阳性)
                        if (IMAGE_DIAGNOSIS.equals(indexEnum) || EXAM_FINDING.equals(indexEnum)) {
                            query.setParameter("firstKeywordContent",
                                    "%" + patientSearchRuleDetail.getFirstKeywordContent() + "%");
                        }
                        if (YIN_YANG.equals(indexEnum)) {
                            //定性结果-只会有包含in 和不包含 not in
                            String[] strings = patientSearchRuleDetail.getFirstKeywordContent().split(",");
                            List<String> factorResultList = Arrays.asList(strings);
                            query.setParameterList("factorResultList", factorResultList);
                        }

                        if (CommonUtils.isNotEmpty(recordStartTime) && CommonUtils.isNotEmpty(recordEndTime)) {
                            query.setParameter("recordStartTime", DateUtil.dateFormate(recordStartTime, "yyyy-MM-dd"));
                            query.setParameter("recordEndTime", DateUtil.dateFormate(recordEndTime, "yyyy-MM-dd"));
                        }
                        query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);

                        List<Map> list = query.list();
                        List<PatientSearchProcess> voList = new ArrayList<>();
                        if (CommonUtils.isNotEmpty(list)) {
                            for (Map map : list) {
                                voList.add(ConversionUtils.convert(map, PatientSearchProcess.class));
                            }
                        } else {
                            voList = new ArrayList<>();
                        }
                        setResult(voList);
                    }
                };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }

    /**
     * 获取检验的关联指标信息
     *
     * @param qo
     * @return
     */
    public List<CrucialRecordResponse> queryExamReportInfo(GroupChronicRecordQo qo) {
        HibernateStatelessResultAction<List<CrucialRecordResponse>> action = new AbstractHibernateStatelessResultAction<List<CrucialRecordResponse>>() {
            @Override
            public void execute(StatelessSession ss) throws Exception {
                StringBuilder sqlBuilder = new StringBuilder();
                sqlBuilder.append("SELECT DISTINCT  " +
                        "  exam_item_code AS indexType,  " +
                        "  exam_item_name AS indexName   " +
                        "FROM  " +
                        "  exam_report  where id_card =:idCard ");
                sqlBuilder.append(" and review_datetime >=:beginTime and review_datetime <=:endTime ");
                Query query = ss.createSQLQuery(sqlBuilder.toString());
                query.setParameter("idCard", qo.getIdCard());
                if (CommonUtils.isNotEmpty(qo.getBeginTime())){
                    query.setParameter("beginTime", qo.getBeginTime()+" 00:00:00");
                }
                if (CommonUtils.isNotEmpty(qo.getBeginTime())){
                    query.setParameter("endTime", qo.getEndTime()+" 23:59:59");
                }
                query.setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP);
                List<Map> list = query.list();
                List<CrucialRecordResponse> voList = new ArrayList<>();
                if (CommonUtils.isNotEmpty(list)) {
                    for (Map map : list) {
                        voList.add(ConversionUtils.convert(map, CrucialRecordResponse.class));
                    }
                } else {
                    voList = new ArrayList<>();
                }
                setResult(voList);
            }
        };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }

    public List<CrucialTimeRecordList> queryExamReportTimeInfo(GroupChronicRecordQo qo, String itemCode) {
        HibernateStatelessResultAction<List<CrucialTimeRecordList>> action = new AbstractHibernateStatelessResultAction<List<CrucialTimeRecordList>>() {
            @Override
            public void execute(StatelessSession ss) throws Exception {
                StringBuilder sqlBuilder = new StringBuilder();
                sqlBuilder.append("SELECT " +
                        " exam_item_code AS indexType, " +
                        " exam_item_name AS indexName, " +
                        " concat(exam_descript,exam_diagnosis) as indexResultContent, " +
                        " review_datetime as crucialTime  " +
                        "FROM " +
                        " exam_report  " +
                        "where exam_item_code =:itemCode and id_card =:idCard ");
                sqlBuilder.append(" and review_datetime >=:beginTime and review_datetime <=:endTime order by review_datetime ");
                Query query = ss.createSQLQuery(sqlBuilder.toString());
                query.setParameter("itemCode", itemCode);
                query.setParameter("idCard", qo.getIdCard());
                if (CommonUtils.isNotEmpty(qo.getBeginTime())){
                    query.setParameter("beginTime", qo.getBeginTime()+" 00:00:00");
                }
                if (CommonUtils.isNotEmpty(qo.getBeginTime())){
                    query.setParameter("endTime", qo.getEndTime()+" 23:59:59");
                }
                query.setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP);
                List<Map> list = query.list();
                List<CrucialTimeRecordList> voList = new ArrayList<>();
                if (CommonUtils.isNotEmpty(list)) {
                    for (Map map : list) {
                        voList.add(ConversionUtils.convert(map, CrucialTimeRecordList.class));
                    }
                } else {
                    voList = new ArrayList<>();
                }
                setResult(voList);
            }
        };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }

    public List<FactorData> executeFactorForRelatedIndicators(FollowUpRouteDetailFactorRelation factorRelation, Date startTime, Date endTime, List<String> patientIdList, Byte isLoopExecute, Long routeDetailId, String followType) {
        HibernateStatelessResultAction<List<FactorData>> action =
                new AbstractHibernateStatelessResultAction<List<FactorData>>() {
                    @Override
                    public void execute(StatelessSession ss) throws Exception {
                        StringBuilder sqlBuilder = new StringBuilder();
                        sqlBuilder.append("select patientId,organizationId,organizationName,patientName ,patientSex," +
                                "indexRecordId,indexCode,indexName,indexResult,reportTime,dataSource from (");
                        sqlBuilder.append("SELECT e.source_patient_id as patientId, e.report_organization as " +
                                "organizationId,'1' as dataSource, ");
                        sqlBuilder.append(" e.report_organization_name as organizationName,e.NAME AS patientName, e" +
                                ".sex AS patientSex,");
                        sqlBuilder.append("exam_report_id AS indexRecordId, exam_type_code AS indexCode, " +
                                "exam_type_name AS indexName,");
                        sqlBuilder.append("exam_diagnosis AS indexResult,  report_datetime AS reportTime ");
                        sqlBuilder.append(" FROM exam_report e  where e.exam_item_code =:indexResultId ");
                        //条件筛选方法：1 范围(包含边界) 2 等于 3 大于 4 小于 5 大于等于 6 小于等于，7包含，8不包含 9 Between
                        Byte conditionFilterMethod = Byte.valueOf(factorRelation.getCompareSign());
                        //检查的，要查询指标编码
                        FusCrucialIndexRecordDAO crucialIndexRecordDAO =
                                DAOFactory.getDAO(FusCrucialIndexRecordDAO.class);
                        FusCrucialIndexRecord fusCrucialIndexRecord =
                                crucialIndexRecordDAO.get(factorRelation.getFactorId());
                        if (fusCrucialIndexRecord == null) {
                            throw new ControllerException("不存在的关联指标，无法完成检索");
                        }
                        InspectIndexEnum indexEnum =
                                InspectIndexEnum.getEnumByKey(fusCrucialIndexRecord.getIndexCode());
                        if (indexEnum == null) {
                            setResult(Collections.emptyList());
                            return;
//                            throw new ControllerException("未实现的关联指标，无法完成检索");
                        }
                        ConditionFilterMethodEnum methodEnum = getEnumByKey(conditionFilterMethod);
                        //检查只有文本和定性(阴阳性)
                        if (IMAGE_DIAGNOSIS.equals(indexEnum)) {
                            switch (methodEnum) {
                                case CONTAIN:
                                    sqlBuilder.append(" and e.exam_diagnosis like :factorResultOne");
                                    break;
                                case NOT_INCLUDED:
                                    sqlBuilder.append(" and e.exam_diagnosis not like :factorResultOne");
                                    break;
                                default:
                                    throw new ControllerException("不合法的运算符");
                            }
                        }
                        if (EXAM_FINDING.equals(indexEnum)) {
                            switch (methodEnum) {
                                case CONTAIN:
                                    sqlBuilder.append(" and e.exam_descript like :factorResultOne");
                                    break;
                                case NOT_INCLUDED:
                                    sqlBuilder.append(" and e.exam_descript not like :factorResultOne");
                                    break;
                                default:
                                    throw new ControllerException("不合法的运算符");
                            }
                        }
                        if (YIN_YANG.equals(indexEnum)) {
                            switch (methodEnum) {
                                case CONTAIN:
                                    sqlBuilder.append(" and e.malignant in (:factorResultList) ");
                                    break;
                                case NOT_INCLUDED:
                                    sqlBuilder.append(" and e.malignant not in (:factorResultList) ");
                                    break;
                                default:
                                    throw new ControllerException("不合法的运算符");
                            }
                        }
                        if (CommonUtils.isNotEmpty(startTime)) {
                            sqlBuilder.append(" and e.report_datetime>=:startTime");
                        }
                        if (CommonUtils.isNotEmpty(endTime)) {
                            sqlBuilder.append(" and e.report_datetime<=:endTime");
                        }
                        if (CommonUtils.isNotEmpty(patientIdList)) {
                            sqlBuilder.append(" and source_patient_id in(:patientIdList) ");
                        }
                        sqlBuilder.append(") AS  m ");
                        //循环执行机制 0 不执行 1 执行
                        if (FollowTypeEnum.FUS_SPECIALIST.getType().equals(followType) && null != isLoopExecute && isLoopExecute == 1) {
                            sqlBuilder.append(" LEFT JOIN fus_factor_data_record f  ON f.patient_id = m.patientId   " +
                                    "AND f.route_detail_id = :routeDetailId AND f.index_record_id = m.indexRecordId " +
                                    "WHERE f.id IS NULL  ");
                        }
                        Query query = ss.createSQLQuery(sqlBuilder.toString());
                        query.setParameter("indexResultId", factorRelation.getIndexResultId());

                        //检查只有文本和定性(阴阳性)
                        if (IMAGE_DIAGNOSIS.equals(indexEnum) || EXAM_FINDING.equals(indexEnum)) {
                            query.setParameter("factorResultOne", "%" + factorRelation.getFactorResultOne() + "%");
                        }
                        if (YIN_YANG.equals(indexEnum)) {
                            //定性结果-只会有包含in 和不包含 not in
                            String[] strings = factorRelation.getFactorResultOne().split(",");
                            List<String> factorResultList = Arrays.asList(strings);
                            query.setParameterList("factorResultList", factorResultList);
                        }

                        if (CommonUtils.isNotEmpty(startTime)) {
                            query.setParameter("startTime", DateUtil.dateFormate(startTime, "yyyy-MM-dd"));
                        }
                        if (CommonUtils.isNotEmpty(endTime)) {
                            query.setParameter("endTime", DateUtil.dateFormate(endTime, "yyyy-MM-dd")+" 23:59:59");
                        }
                        if (CommonUtils.isNotEmpty(patientIdList)) {
                            query.setParameterList("patientIdList", patientIdList);
                        }
                        if (FollowTypeEnum.FUS_SPECIALIST.getType().equals(followType) && null != isLoopExecute && isLoopExecute == 1) {
                            query.setParameter("routeDetailId", routeDetailId);
                        }
                        query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);

                        List<Map> list = query.list();
                        List<FactorData> voList = new ArrayList<>();
                        if (CommonUtils.isNotEmpty(list)) {
                            for (Map map : list) {
                                voList.add(ConversionUtils.convert(map, FactorData.class));
                            }
                        } else {
                            voList = new ArrayList<>();
                        }
                        setResult(voList);
                    }
                };
        HibernateSessionTemplate.instance().execute(action);
        return action.getResult();
    }
}
